package pers.mihao.quickstream.common.plus.store;

import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import pers.mihao.quickstream.common.exception.BaseException;

import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author mihao
 * @since 2022/8/22
 */
@Component
public class LocalFileStore extends AbstractStore implements EnvironmentAware {

    @Value("${spring.store.file.path:}")
    String basePath;

    Environment environment;

    @Override
    protected void init() {
        if (basePath.length() == 0) {
            basePath = environment.getProperty("home") + File.separator;
        }
    }

    @Override
    protected int doSave(String nameSpace, Serializable key, Object entry) {
        try {
            Path path = Paths.get(nameSpace);
            if (!Files.exists(path)) {
                Files.createFile(path);
            }
            Map<String, FileStoreInfo> map = readAll(path);
            String keyStr = key.toString();
            if (!map.containsKey(keyStr)) {
                String info = (keyStr + "=" + JSONObject.toJSONString(new FileStoreInfo(entry, map.size())));
                Files.write(path, info.getBytes());
                return 1;
            } else {
                FileStoreInfo fileStoreInfo = map.get(keyStr);
                fileStoreInfo.info = entry;
                clean(path);
                writeAll(map, path);
                return 0;
            }
        } catch (IOException e) {
            throw new BaseException(e);
        }
    }

    private void writeAll(Map<String, FileStoreInfo> map, Path path) throws IOException {
        List<String> fileStoreInfos = map.entrySet().stream()
                .sorted(Comparator.comparingInt(e -> e.getValue().index))
                .map(e -> e.getKey() + "+" + JSONObject.toJSONString(e.getValue()))
                .collect(Collectors.toList());
        Files.write(path, fileStoreInfos);
    }

    private void clean(Path path) throws IOException {
        Files.delete(path);
        Files.createFile(path);
    }

    private Map<String, FileStoreInfo> readAll(Path path) throws IOException {
        List<String> strings = Files.readAllLines(path, StandardCharsets.UTF_8);
        return strings.stream()
                .collect(Collectors.toMap(s -> s.substring(0, s.indexOf("="))
                        , s -> JSONObject.parseObject(s.substring(s.indexOf("=") + 1), FileStoreInfo.class)));
    }

    @Override
    public void setEnvironment(Environment environment) {
        this.environment = environment;
    }

    static class FileStoreInfo {
        Object info;
        Integer index;

        public FileStoreInfo(Object info, Integer index) {
            this.info = info;
            this.index = index;
        }

        public Object getInfo() {
            return info;
        }

        public void setInfo(Object info) {
            this.info = info;
        }

        public Integer getIndex() {
            return index;
        }

        public void setIndex(Integer index) {
            this.index = index;
        }
    }


}
